-- @author QueuedResonance 2022

local Animations = {}

local ZomboWinActType = ZomboWinActType
local ZomboWinAnimationData = ZomboWinAnimationData

local string = string
local pairs = pairs
local type = type

animationPairs = {
	Consent_BJ_M = "Consent_BJ_F",
	Consent_Cowgirl_M = "Consent_Cowgirl_F",
	Consent_Doggy_M = "Consent_Doggy_F",
	Consent_Missionary_M = "Consent_Missionary_F",
	Consent_OralDomination_M = "Consent_OralDomination_F",
	Consent_SideFuck_M = "Consent_SideFuck_F",
	Consent_Tower_M = "Consent_Tower_F",
	Defeat_Doggy_M = "Defeat_Doggy_F",
	Defeat_DoggyDomination_M = "Defeat_DoggyDomination_F",
	Defeat_KneeBJ_M = "Defeat_KneeBJ_F",
	Defeat_MissionaryFear_M = "Defeat_MissionaryFear_F",
	Defeat_Stand_Fuck_M = "Defeat_Stand_Fuck_F",
	male1 = "female1",
	male2 = "female2",
	male4 = "female4",
	male6 = "female6",
	male7 = "female7",
	blabla_PreDefeat_f2b_01_M = "blabla_PreDefeat_f2b_01_F",
	blabla_PreDefeat_f2f_01_M = "blabla_PreDefeat_f2f_01_F",
	
	Consent_BJ_F = "Consent_BJ_M",
	Consent_Cowgirl_F = "Consent_Cowgirl_M",
	Consent_Doggy_F = "Consent_Doggy_M",
	Consent_Missionary_F = "Consent_Missionary_M",
	Consent_OralDomination_F = "Consent_OralDomination_M",
	Consent_SideFuck_F = "Consent_SideFuck_M",
	Consent_Tower_F = "Consent_Tower_M",
	Defeat_Doggy_F = "Defeat_Doggy_M",
	Defeat_DoggyDomination_F = "Defeat_DoggyDomination_M",
	Defeat_KneeBJ_F = "Defeat_KneeBJ_M",
	Defeat_MissionaryFear_F = "Defeat_MissionaryFear_M",
	Defeat_Stand_Fuck_F = "Defeat_Stand_Fuck_M",
	female1 = "male1",
	female2 = "male2",
	female4 = "male4",
	female6 = "male6",
	female7 = "male7",
	blabla_PreDefeat_f2b_01_F = "blabla_PreDefeat_f2b_01_M",
	blabla_PreDefeat_f2f_01_F = "blabla_PreDefeat_f2f_01_M"
}

--- Returns the first occurrence of this element, if not, returned nil
-- @param list: array of the list to search the element in
-- @param element: the object to search for in the list
function Animations:tableFind(list, element)
	for i = 1, #list do
		local item = list[i]
		if item == element then
			return item
		end
	end
end

--- Returns a list of viable animations to fetch depending on factors listed below
-- @param actorCount: number of actors participating in the animation
-- @param males: number of males present in the animation
-- @param females: number of females present in the animation
-- @param tagsToSearch: an array of tags used to return animations containing them (ie. {"Missionary", "Doggystyle"} will return all animations with these tags)
-- @param tagsBlacklist: an array of tags used to ignore animations with these tags (ie. {"Aggressive", "Blowjob"} will ignore animations with these tags)
-- @param allTagsRequired: defaults to true, all tags in tagsToSearch must be valid in the animation to be returned, false will return the animation if one tag is valid
function Animations:getAnimations(actorCount, males, females, tagsToSearch, tagsBlacklist, allTagsRequired)
	males = males or -1
	females = females or -1
	tagsToSearch = tagsToSearch or {}
	tagsBlacklist = tagsBlacklist or {}
	allTagsRequired = allTagsRequired or true

	local viableAnimations = {}

	-- Loop through all the animations
	for i = 1, #ZomboWinAnimationData do
		local animation = ZomboWinAnimationData[i]
		local tags = animation.tags
		local tagsFound = 0
		local canAdd = true

		if #animation.actors == actorCount then
			-- Check for blacklisted tags
			for _, blacklistedTag in ipairs(tagsBlacklist) do
				if Animations:tableFind(tags, blacklistedTag) then
					canAdd = false
					break
				end
			end

			-- Check for required tags
			for _, searchTag in ipairs(tagsToSearch) do
				if Animations:tableFind(tags, searchTag) then
					tagsFound = tagsFound + 1
				end
			end

			-- Check if all required tags are found
			if allTagsRequired and tagsFound < #tagsToSearch then
				canAdd = false
			end

			-- Check for gender counts
			local maleCount = 0
			local femaleCount = 0
			for _, actor in ipairs(animation.actors) do
				if actor.gender == "Male" then
					maleCount = maleCount + 1
				elseif actor.gender == "Female" then
					femaleCount = femaleCount + 1
				end
			end

			if males >= 0 and maleCount ~= males then
				canAdd = false
			end

			if females >= 0 and femaleCount ~= females then
				canAdd = false
			end

			if canAdd then
				table.insert(viableAnimations, animation)
			end
		end
	end

	return viableAnimations
end


--- Returns a list of viable animations to fetch depending on factors listed below
-- @param the animation list, usually Animations.Client.Animations
-- @param boolean is it le... female?
-- @param boolean is the act consensual
-- @param boolean can this act be used with zombies
function Animations:getZLAnimations(list, isFemale, isConsensual, isZombie)
	local viableAnimations = {}

	for _, animation in ipairs(list) do
		local data = ZomboWinAnimationData[animation]

		if data then
			local canAdd = true

			--- Check if the animations are gender compatible
			if isFemale then
				if not data.Animations.Female then
					canAdd = false
				end
			else
				if not data.Animations.Male then
					canAdd = false
				end
			end

			--- Check if the animations can be used with zombie
			if isZombie ~= nil and isZombie ~= data.IsZombieAllowed then
				canAdd = false
			end

			--- Check if the animations are consensual
			if isConsensual ~= nil and isConsensual ~= data.IsConsensual then
				canAdd = false
			end

			if canAdd then
				table.insert(viableAnimations, {Key = animation, Data = data})
			end
		end
	end

	return viableAnimations
end

return Animations